package com.javabank.ws.logic;

import java.util.Date;
import java.util.Random;

import sun.util.logging.resources.logging;

import com.javabank.ws.dao.DAOFacade;
import com.javabank.ws.domain.Account;
import com.javabank.ws.domain.Transaction;

public class Logic {
	private DAOFacade facade;
	private Rules rules;
	
	/**
	 * Constructor
	 * @param facade
	 */
	public Logic(DAOFacade facade) {
        this.facade = facade;
        this.rules = new Rules();
    }
	
	/**
	 * Retrieve bankaccount using bankaccountnumber as identifier
	 * @param rekeningnummer
	 * @return
	 */
	public Account getAccountByRekeningnummer(int rekeningnummer) {
		return this.facade.getAccountDAO().getByRekening(rekeningnummer);
	}
	
	/**
	 * Create a bankaccount
	 * @param account
	 */
	public void addAccount(Account account) {
		/*
		 * Rekeningnummer van nieuw account mist nog.
		 * Voor schoolopdracht mag client wel zelf saldo en limiet opgeven.
		 * Gebruiker Random voor genereren random nummer tussen 1 en 999999999 
		 * (we houden in de schoolopgave geen rekening met elfproef)
		 */
		Random generator = new Random();
		int randomRekeningnummer;
		
		/*
		 * Net zo lang rekeningnummer genererer tot er een nog niet gebruikt nummer gevonden is.
		 */
		do{
			randomRekeningnummer = generator.nextInt(999999999) + 1;
		}
		while(!rules.rekeningnummerIsUnique(randomRekeningnummer));
				
		account.setRekeningnummer(randomRekeningnummer);
		
		this.facade.getAccountDAO().add(account);
	}
	
	/**
	 * Mutate a bankaccount.
	 * @param account
	 */
	public void updateAccount(Account account) {
		this.facade.getAccountDAO().update(account);
	}
	
	/**
	 * Transfer money from one account to another.
	 * Rules:
	 * - sender and receiver have to exist
	 * - sender has to have enough balance
	 * - the whole transaction has to be atomic
	 * 
	 * @param amount
	 * @param reknummerFrom
	 * @param reknummerTo
	 * @return boolean
	 */
	public boolean transfer(float amount, int reknummerFrom, int reknummerTo) {
		Account from = facade.getAccountDAO().getByRekening(reknummerFrom);
		Account to = facade.getAccountDAO().getByRekening(reknummerTo);
		
		if(from == null || to == null) {
			// sender and receiver have to exist
			return false;
		}
		
		if(!rules.hasEnoughBalance(from, amount)){
			// sender has to have enough balance
			return false;
		}

		// Nieuwe transactie
		Transaction transaction = new Transaction();
		// Bedrag van transactie
		transaction.setBedrag(amount);
		// Datum van transactie (nu)
		transaction.setDatum(new Date());
		
		// afzender saldo aanpassen
		from.setSaldo(from.getSaldo()-amount);
		transaction.setFrom(from);
		
		// ontvanger saldo aanpassen
		to.setSaldo(to.getSaldo()+amount);
		transaction.setTo(to);
		
		this.facade.getTransactionDAO().add(transaction);
		
		return true;
	}
	
	/**
	 * Retrieve a single transaction by its PK.
	 * @param id
	 * @return Transaction
	 */
	public Transaction getTransactionById(int id) {
		return this.facade.getTransactionDAO().getById(id);
	}
	
	public Transaction[] getTransactions(int rekeningnr, Date datum) {
		return this.facade.getTransactionDAO().getTransactionsByReknr(rekeningnr, datum);
	}
}
